package org.dei.perla.sys.device.channel.frame.header.concrete.simple;

import org.dei.perla.sys.device.channel.frame.address.concrete.SimpleFrameAddress;
import org.dei.perla.sys.device.channel.frame.header.FrameHeaderReceiver;

/**
 * Il ricevitore di header di tipo SimpleFrameHeader.
 * Suppone di ricevere prima l'indirizzo sorgente e poi quello destinazione.
 */
public class SimpleFrameHeaderReceiver extends FrameHeaderReceiver {

	private byte []pByteSourceAddress;
	private byte []pByteDestAddress;
	private int pPosReceived;
	private boolean pReceivingSource;
	
	public SimpleFrameHeaderReceiver() {

		this.pByteDestAddress 	= new byte[4];
		this.pByteSourceAddress = new byte[4];
		reset();
	
	}
	
	@Override
	public void receiveByte(byte parReceivedByte) {
		
		// Sto ricevendo l'indirizzo sorgente
		if ( this.pReceivingSource ) { 
			
			this.pByteSourceAddress[this.pPosReceived] = parReceivedByte;
			this.pPosReceived++;
		
		// Sto ricevendo l'indirizzo destinazione
		} else {
			
			this.pByteDestAddress[this.pPosReceived] = parReceivedByte;
			this.pPosReceived++;
			
		}
		
		// Ho ricevuto un indirizzo completo
		if ( this.pPosReceived == 4 ) {
			
			// Ho ricevuto l'indirizzo sorgente
			if ( this.pReceivingSource ) {
				
				this.pReceivingSource = ! this.pReceivingSource;
				this.pPosReceived = 0;
			
			// Ho ricevuto anche l'indirizzo destinazione ...
			} else {
				
				this.pReceivingSource = ! this.pReceivingSource;
				
				SimpleFrameHeader addr = new SimpleFrameHeader();
				addr.setSourceAddress(new SimpleFrameAddress(byteArrayToInt(this.pByteSourceAddress)));
				addr.setDestinationAddress(new SimpleFrameAddress(byteArrayToInt(this.pByteDestAddress)));
				
				// Devo notificarne la ricezione
				this.pFrameAddressEvents.onFrameHeaderReceived(addr);
				reset();
			}
			
		}

	}

	@Override
	public void reset() {
		this.pPosReceived 		= 0;
		this.pReceivingSource 	= true;
	}
	
	/**
	 * Converte un array di 4 bytes nell'intero relativo
	 * @param b Array di 4 byte
	 * @return Restituisce un intero
	 */
	private int byteArrayToInt(byte[] b) {
			
		int value = 0;
		
		for (int i = 0; i < 4; i++) {
				
			int shift = (4 - 1 - i) * 8;
			value += (b[i] & 0x000000FF) << shift;
		
		}
		
		return value;
		
	}

}
